using System;
using System.Collections.Generic;
using System.Text;

namespace MyLib
{
    public class ListUtil
    {
        public static T First<T>(List<T> list)
        {
            if (list.Count > 0)
            {
                return list[0];
            }
            return default(T);
        }

        public static T Last<T>(List<T> list)
        {
            if (list.Count > 0)
            {
                return list[list.Count-1];
            }
            return default(T);
        }

        public static void Distinct<T>(List<T> list, string propertyName) where T : class, new()
        {
            for (int i = list.Count-1; i >= 0; i--)
            {
                object value = typeof(T).GetProperty(propertyName).GetValue(list[i], null);
                int index = FindIndex<T>(list, propertyName, value);
                if (!index.Equals(i))
                {
                    list.RemoveAt(i);
                }
            }
        }

        public static decimal Sum<T>(List<T> list, string propertyName) where T : class, new()
        {
            decimal sum = 0;
            foreach (T t in list)
            {
                object value = typeof(T).GetProperty(propertyName).GetValue(t, null);
                if (value != null)
                {
                    sum += ConvertUtil.ToDecimal(value);
                }
            }
            return sum;
        }

        public static decimal Average<T>(List<T> list, string propertyName) where T : class, new()
        {
            decimal sum = Sum<T>(list, propertyName);
            if (list.Count > 0)
            {
                sum = sum / list.Count;
            }
            return sum;
        }

        public static T Find<T>(List<T> list, string propertyName, object propertyValue) where T : class, new()
        {
            T t=list.Find(delegate(T item)
            {
                object value = item.GetType().GetProperty(propertyName).GetValue(item, null);
                return Comparer<T>.Equals(propertyValue,value);
            });
            return t;
        }

        public static List<T> FindAll<T>(List<T> list, string propertyName, object propertyValue) where T : class, new()
        {
            return list.FindAll(delegate(T item)
            {
                object value = item.GetType().GetProperty(propertyName).GetValue(item, null);
                return Comparer<T>.Equals(propertyValue, value);
            });
        }

        public static int FindIndex<T>(List<T> list, string propertyName, object propertyValue) where T : class, new()
        {
            return list.FindIndex(delegate(T item)
            {
                object value = item.GetType().GetProperty(propertyName).GetValue(item, null);
                return Comparer<T>.Equals(propertyValue, value);
            });
        }

        public static void Sort<TObject, TProperty>(List<TObject> list, string propertyName) where TObject : class ,new()
        {
            Sort<TObject, TProperty>(list, propertyName, SortingDirection.Ascending);
        }

        public static void Sort<TObject, TProperty>(List<TObject> list, string propertyName, SortingDirection sortingDirection) where TObject : class, new()
        {
            list.Sort(delegate(TObject itemA, TObject itemb)
            {
                TProperty valueToCompareWith = (TProperty)itemA.GetType().GetProperty(propertyName).GetValue(itemA, null);
                TProperty valueToBeCompared = (TProperty)itemb.GetType().GetProperty(propertyName).GetValue(itemb, null);
                return (int)sortingDirection * Comparer<TProperty>.Default.Compare(valueToCompareWith, valueToBeCompared);
            });
        }

        public enum SortingDirection
        {
            Ascending = 1,
            Descending = -1
        }
    }
}
